package cn.liumouren.tool.security.autoconfigure.config;

import cn.liumouren.tool.security.autoconfigure.component.interceptor.ApiMeasureInterceptor;
import cn.liumouren.tool.security.core.DlInterceptor;
import cn.liumouren.tool.security.core.DlInterceptorRegistry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Daniel Liu
 * @date 2021/3/11 12:37
 */
@Slf4j
@Configuration
@ConditionalOnProperty(value = "dl.security.enable", havingValue = "true", matchIfMissing = true)
public class InterceptorConfiguration {


    /**
     * 如果启用, 正常注入
     */
    @Bean
    public DlInterceptorRegistry dlInterceptorRegistry(List<DlInterceptor> interceptors) {
        return new DlInterceptorRegistry() {
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                for (DlInterceptor in : interceptors) {
                    // 额外添加排除 /* -> /*/
                    List<String> exclude = in.getExcludePatterns().stream().map(path -> {
                        if (path.length() > 1 && path.endsWith("*") && !path.endsWith("**")) {
                            return path + "/";
                        }
                        return path;
                    }).collect(Collectors.toList());
                    // 添加  /* -> /*/
                    List<String> path = in.getUrlPatterns().stream().map(p -> {
                        if (p.length() > 1 && p.endsWith("*") && !p.endsWith("**")) {
                            return p + "/";
                        }
                        return p;
                    }).collect(Collectors.toList());

                    registry.addInterceptor(in)
                            .addPathPatterns(new ArrayList<>(in.getUrlPatterns()))
                            .addPathPatterns(path)
                            .excludePathPatterns(new ArrayList<>(in.getExcludePatterns()))
                            .excludePathPatterns(exclude)
                            .excludePathPatterns("/error") //如果spring mvc未找到路由, 会转发到/error, 会再次进入拦截器, exclude防止进入拦截器两次
                            .order(in.getOrder());
                }
            }
        };
    }


    @Bean
    @ConditionalOnProperty(value = "dl.security.open-api-measure", havingValue = "true", matchIfMissing = true)
    public DlInterceptor apiMeasureInterceptor() {
        ApiMeasureInterceptor apiMeasureInterceptor = new ApiMeasureInterceptor();
        apiMeasureInterceptor.addPatterns("/**");
        apiMeasureInterceptor.setOrder(Integer.MIN_VALUE + 100);
        return apiMeasureInterceptor;
    }

}